﻿using ELTE.TFEG.Hough.Controls;
using ELTE.TFEG.ImageTransform;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Drawing;
using ELTE.TFEG.Hough.Enums;
using ELTE.TFEG.Hough.EventHandling;

namespace ELTE.TFEG.Hough
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //get the image directory from where the images will loaded
        string imgDir = ELTE.TFEG.Hough.Properties.Settings.Default.ImageDirectory;

        //a processor for image transformation like grayscaling, edge detecting etc.
        ImageProcess preProcessor = new ImageProcess();

        //the image source to display in case no image is selected
        BitmapImage no_img_image = new BitmapImage(new Uri("Images/no-image.png", UriKind.Relative));
        //a variable where we store the data of the currently selected image (to process)
        BitmapImage currentlySelectedImage;
        //a variable where we store the data of the currently selected image's grayscaled version
        BitmapImage currentlySelectedGrayScaleImage;

        DisplayStage currentStage;

        string[] filesInDirectory;

        public MainWindow()
        {
            InitializeComponent();

            //1. set the current stage to loading images
            //(it will be changed on specific events)
            //2. add a new event handler to when a filter is applied to an image 
            //(to be able to show what happened, according to the event based async pattern)

            preProcessor.eventHandling.FilterApplied += eventHandling_FilterApplied;
            preProcessor.houghEventHandling.TransformEvent += houghEventHandling_TransformEvent;
            currentStage = DisplayStage.StageLoadingImages;
            ReadImages();
        }

        void houghEventHandling_TransformEvent(object sender, HoughTransformEventargs args)
        {
            this.lblInfo.Content = args.Message;
            this.lblInfo.InvalidateVisual();
        }

        

        void eventHandling_FilterApplied(object sender, EventHandling.FilterAppliedEventArgs args)
        {
            string filterAppliedFormatString = "Filter '{0}' applied.";
            switch (args.FilterName)
            {
                case Constants.homFilterName:
                    this.lblInfo.Content = String.Format(filterAppliedFormatString, args.FilterName);
                    break;
                case Constants.canFilterName:
                    this.lblInfo.Content = String.Format(filterAppliedFormatString, args.FilterName);
                    break;
                case Constants.diffFilterName:
                    this.lblInfo.Content = String.Format(filterAppliedFormatString, args.FilterName);
                    break;
                case Constants.sobFilterName:
                    this.lblInfo.Content = String.Format(filterAppliedFormatString, args.FilterName);
                    break;
                default:
                    break;

            }
        }

        private void ReadImages()
        {
            try
            {
                
                //get all the files in the directory
                this.filesInDirectory = Directory.GetFiles(imgDir);
                //check if we have any file available
                if (filesInDirectory != null && filesInDirectory.Length > 0)
                {
                    var imagesInDir = filesInDirectory
                        .Where(f => (f.EndsWith(".jpg") || f.EndsWith(".png"))
                            && !f.Contains("_thumb")
                            && !f.Contains(Constants.canFilterSuffix)
                            && !f.Contains(Constants.diffFilterSuffix)
                            && !f.Contains(Constants.grayScaleSuffix)
                            && !f.Contains(Constants.homFilterSuffix)
                            && !f.Contains(Constants.sobFilterSuffix)
                            )
                        .ToList();

                    imagesInDir.ForEach(img =>
                    {
                        ImageThumbnailControl ctrl = new ImageThumbnailControl(img);
                        ctrl.btnImg.Click += btnImg_Click;
                        this.stackImgList.Children.Add(ctrl);

                    });
                }
                else
                {
                    MessageBox.Show("Nincsenek képek a " + imgDir + " könyvtárban");
                }
            }
            catch (Exception ex)
            {

            }

        }

        void btnImg_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                //check if the button is already selected
                Button source = sender as Button;
                if (source != null)
                {
                    ImageThumbnailControl parentUC = ((Border)source.Parent).Parent as ImageThumbnailControl;
                    if (parentUC != null)
                    {
                        if (parentUC.Selected)
                        {
                            parentUC.Deselect();
                            //unload the other images
                            UnLoadImages();
                        }
                        else
                        {
                            //check if any of the other user controls in the container stackpanel 
                            //is selected, and if so, deselect it.
                            foreach (var child in this.stackImgList.Children)
                            {
                                ImageThumbnailControl childControl = child as ImageThumbnailControl;
                                if (childControl != null && childControl.Selected)
                                {
                                    childControl.Deselect();
                                }
                            }
                            parentUC.Select();
                            currentlySelectedImage = parentUC.Image;
                            LoadImageForPreprocessing(currentlySelectedImage);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }

        private void UnLoadImages()
        {
            this.imgBefore.SetImage(no_img_image);
        }

        private void LoadImageForPreprocessing(BitmapImage image)
        {
            //load the image in the top left big image
            this.imgBefore.SetImage(image);
            //enable the "next" button.
            this.btnNext.Visibility = System.Windows.Visibility.Visible;
        }

        private void btnPrev_MouseUp_1(object sender, MouseButtonEventArgs e)
        {

        }

        private void btnNext_MouseUp_1(object sender, MouseButtonEventArgs e)
        {
            switch (this.currentStage)
            {
                case DisplayStage.StageGrayScaling:
                    GenerateHough();
                    this.currentStage = DisplayStage.StageHoughForLines;
                    break;
                case DisplayStage.StageHoughForLines:
                    break;
                case DisplayStage.StageLoadingImages:
                    FillPreprocessedImages();
                    this.currentStage = DisplayStage.StageGrayScaling;
                    break;
            }

        }

        private void FillPreprocessedImages()
        {
            List<Bitmap> edgeDetectedImages = new List<Bitmap>();
            //Check if edge detected images are available
            string cannyFilteredFilePath = this.currentlySelectedImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.canFilterSuffix);
            bool edgeDetectedImagesAreAvailable = this.filesInDirectory.Contains(cannyFilteredFilePath);
            if (edgeDetectedImagesAreAvailable)
            {
                //load them.
                string homogenityFilteredFilePath = this.currentlySelectedImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.homFilterSuffix);
                string differenceFilteredFilePath = this.currentlySelectedImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.diffFilterSuffix);
                string sobelFilteredFilePath = this.currentlySelectedImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.sobFilterSuffix);
                List<string> filePaths = new List<string> 
                { 
                    cannyFilteredFilePath,
                    homogenityFilteredFilePath,
                    differenceFilteredFilePath,
                    sobelFilteredFilePath
                };
                filePaths.ForEach(path => edgeDetectedImages.Add(new Bitmap(path)));
            }
            else
            {
                string grayScaledImagePath = this.currentlySelectedImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.grayScaleSuffix);
                //Check if a grayscaled image is available
                if (filesInDirectory.Contains(grayScaledImagePath))
                {
                    //load the grayscaled image
                    Bitmap grayScaledImage = new Bitmap(grayScaledImagePath);
                    //use the preprocessors GetEdgeDetectedImages method with the grayscaled image

                    edgeDetectedImages = preProcessor.GetEdgeDetectedImages(grayScaledImage);
                }
                else
                {
                    edgeDetectedImages = preProcessor.GetEdgeDetectedImages(this.currentlySelectedImage);
                }
            }
            
            //loop through each image
            edgeDetectedImages.ForEach(img =>
            {
                ZoomableImage zImg = new ZoomableImage(img.GetBitmapImage());
                zImg.Width = this.stackPreProcessedImages.RenderSize.Width / edgeDetectedImages.Count;
                zImg.Height = this.stackPreProcessedImages.RenderSize.Height * 0.8;
                zImg.borderImg.MouseLeftButtonUp += borderImg_MouseLeftButtonUp;
                //zImg.SetZoom(-.6);
                //zImg.borderImg.Width = zImg.imgToShow.Width;
                //zImg.borderImg.Height = zImg.imgToShow.Height;
                this.stackPreProcessedImages.Children.Add(zImg);

            }
                );
        }

        void borderImg_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Border border = sender as Border;
            if (border != null)
            {
                System.Windows.Controls.Image img = border.Child as System.Windows.Controls.Image;
                this.currentlySelectedGrayScaleImage = img.Source as BitmapImage;
                //find the selected border
                foreach (var item in this.stackPreProcessedImages.Children)
                {
                    if (item.GetType() == typeof(ZoomableImage))
                    {
                        ZoomableImage zImg = item as ZoomableImage;
                        if (zImg != null)
                        {
                            if (zImg.borderImg == border)
                            {
                                zImg.ToggleSelect();
                            }
                            else
                            {
                                if (zImg.Selected)
                                {
                                    //we found the currently selected
                                    zImg.ToggleSelect();
                                    //break;
                                }
                            }
                        }
                    }
                }

            }
            else
            {

            }


        }

        private void GenerateHough()
        {
            foreach (var item in this.stackPreProcessedImages.Children)
            {
                if (item.GetType() == typeof(ZoomableImage))
                {
                    ZoomableImage zImg = item as ZoomableImage;
                    if (zImg.Selected)
                    {
                        Bitmap houghTransformResult = preProcessor.GetHoughLine(zImg.imgToShow.Source as BitmapImage, 50);
                        if (houghTransformResult != null)
                        {
                            houghTransformResult.Save(
                                this.currentlySelectedImage
                                .UriSource
                                .OriginalString
                                .AddSuffixToFilePath(Constants.houghFilterSuffix)
                                .Replace(".jpg", ".png"), ImageFormat.Png);
                            this.stackResults.Children.Add(new ZoomableImage(houghTransformResult.GetBitmapImage()));
                        }
                    }
                }
            }
        }
    }
}
